package org.apmap.servlets;

import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.apmap.forms.RegistrationForm;
import org.apmap.base.User;
import org.apmap.base.Main;
import org.apmap.mail.SendMail;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegistrationAction extends Action {

    public static Pattern EMAIL_PATTERN = Pattern.compile("(\\w+)@(\\w+\\.)(\\w+)(\\.\\w+)*");

    public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
        RegistrationForm registrationForm = (RegistrationForm) form;

        try {
            checkForm(registrationForm);
            saveUser(registrationForm);
            sendMail(registrationForm);
        } catch (Exception e) {
            request.getSession().setAttribute("error", e.getMessage());
            return mapping.findForward("registration");
        }

        return mapping.findForward("registrationDone");
    }

    public void saveUser(RegistrationForm registrationForm) throws Exception {

        Session hibsession = Main.getSession();
        Transaction transaction = hibsession.beginTransaction();
        try {
            User user = new User();
            user.setLogin(registrationForm.getEmail());
            user.setPassword(registrationForm.getPassword());
            Map<String, String> profile = new HashMap<String, String>();
            profile.put("name", registrationForm.getName());
            user.setProfile(profile);

//            Balance balance = new Balance(new Date(), 100.0);
//            balance.setUid(user);
//            user.setBalanceList(Collections.singletonList(balance));
            
            hibsession.save(user);
            hibsession.flush();

            transaction.commit();
        } catch (Exception ex) {
            transaction.rollback();
            throw ex;
        }

        finally {
            hibsession.close();
        }
    }

    public void sendMail(RegistrationForm form) throws Exception {
        String subject = "welcome";
        String text = "Hello, " + form.getName() + " !\n" +
                "Now your can login to http://dimazaur.dyndns.org:8080\n" +
                "by " + form.getEmail() + "/" + form.getPassword() + "\n";

        SendMail.send(form.getEmail(), subject, text);
    }

    public void checkUser(RegistrationForm registrationForm) throws IllegalArgumentException {
        Session hibsession = Main.getSession();
        final Query query = hibsession.createQuery("from User where login=:login");
        query.setString("login", registrationForm.getEmail());
        List list = query.list();
        hibsession.close();
        if (list.size() != 0) {
            throw new IllegalArgumentException("user with the same login already exists");
        }
    }

    public void checkForm(RegistrationForm registrationForm) throws IllegalArgumentException {
        if (!hasValue(registrationForm.getEmail())) {
            throw new IllegalArgumentException("set email");
        }
        if (!EMAIL_PATTERN.matcher(registrationForm.getEmail()).matches()) {
            throw new IllegalArgumentException("invalid email");
        }
        if (!hasValue(registrationForm.getPassword())) {
            throw new IllegalArgumentException("set password");
        }
        if (!hasValue(registrationForm.getPassword2())) {
            throw new IllegalArgumentException("set password 2");
        }
        if (!registrationForm.getPassword().equals(registrationForm.getPassword2())) {
            throw new IllegalArgumentException("password and password 2 has to be equals");
        }
        if (!hasValue(registrationForm.getName())) {
            throw new IllegalArgumentException("set name");
        }
        if (!hasValue(registrationForm.getContactInfo())) {
            throw new IllegalArgumentException("set contact info");
        }
    }

    public boolean hasValue(String str) {
        return str != null && !str.isEmpty();
    }
}